﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;

namespace CSP.Receivers
{
    class InternetConfigFileFeatureReceiver : ConfigFileFeatureReceiver
    {
        /*

<system.web>
          <authentication mode="Forms">
      <forms loginUrl="/sites/cuesco2/Pages/sign_up.aspx" />
    </authentication>
        */

        protected string _defaultMembershipProvider = "AspNetMembershipProvider";
        protected string _connectionStringName = "AspNetMembershipSQL";
        protected string _connectionStringContent = "Data Source=(local);Initial Catalog=AspNetDb;Trusted_Connection=yes;";

        protected string _servicePrincipalName = "host/localhost";
        protected string _defaultMembershipRoleProvider = "AspNetMembershipRoleProvider";
        protected string _defaultEndPointAddress = "http://localhost/MembershipServiceClass.svc";

        /// <summary>
        /// Gets the connection string from the machine's registry
        /// </summary>
        protected string ConnectionStringContent
        {
            get
            {
                try
                {
                    return CSP.Core.RegistryAccess.GetStringProperty(Registry.LocalMachine, CSP.Core.Constants.CspRegistryKey, "FBAConnectionString");
                }
                catch (Exception ex)
                {
                    return _connectionStringContent;
                }
            }
        }

        /// <summary>
        /// Gets the service principal name from the machine's registry
        /// </summary>
        protected string ServicePrincipalName
        {
            get
            {
                try
                {
                    return CSP.Core.RegistryAccess.GetStringProperty(Registry.LocalMachine, CSP.Core.Constants.CspRegistryKey, "WCFServicePrincipalName");
                }
                catch (Exception ex)
                {
                    return _servicePrincipalName;
                }
            }
        }

        /// <summary>
        /// Gets the default end point address from the machine's registry
        /// </summary>
        protected string DefaultEndPointAddress
        {
            get
            {
                try
                {
                    return CSP.Core.RegistryAccess.GetStringProperty(Registry.LocalMachine, CSP.Core.Constants.CspRegistryKey, "WCFEndPointURL");
                }
                catch (Exception ex)
                {
                    return _defaultEndPointAddress;
                }
            }
        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as section nodes.
        /// </summary>
        protected override ModificationEntry[] GetSectionEntries() 
        {
            List<ModificationEntry> modifications = new List<ModificationEntry>();
            //Add Section nodes
            modifications.Add(new ModificationEntry("appSettings", "configuration","appSettings"));
            modifications.Add(new ModificationEntry("connectionStrings", "configuration","connectionStrings"));
            modifications.Add(new ModificationEntry("membership", "configuration/system.web","membership"));
            modifications.Add(new ModificationEntry("providers", "configuration/system.web/membership","providers"));
            modifications.Add(new ModificationEntry("roleManager", "configuration/system.web","roleManager"));
            modifications.Add(new ModificationEntry("providers", "configuration/system.web/roleManager","providers"));
            modifications.Add(new ModificationEntry("authentication", "configuration/system.web","authentication"));
            modifications.Add(new ModificationEntry("forms", "configuration/system.web/authentication","forms"));
            modifications.Add(new ModificationEntry("system.serviceModel", "configuration","system.serviceModel"));
            modifications.Add(new ModificationEntry("bindings", "configuration/system.serviceModel","bindings"));
            modifications.Add(new ModificationEntry("wsHttpBinding", "configuration/system.serviceModel/bindings","wsHttpBinding"));
            modifications.Add(new ModificationEntry("binding", "configuration/system.serviceModel/bindings/wsHttpBinding","binding"));
            modifications.Add(new ModificationEntry("client", "configuration/system.serviceModel","client"));
            modifications.Add(new ModificationEntry("endpoint", "configuration/system.serviceModel/client","endpoint"));
            modifications.Add(new ModificationEntry("identity", "configuration/system.serviceModel/client/endpoint", "identity"));
            return modifications.ToArray();

        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as child nodes.
        /// </summary>
        protected override ModificationEntry[] GetChildNodeEntries()
        {
            List<ModificationEntry> modifications = new List<ModificationEntry>();
            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _connectionStringName),
                    "configuration/connectionStrings",
                    string.Format(@"<add name=""{0}"" connectionString=""{1}"" />", _connectionStringName, ConnectionStringContent))
                    );

            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _defaultMembershipProvider),
                    "configuration/system.web/membership/providers",
                    string.Format(@"<add name=""{0}"" connectionStringName=""{1}"" enablePasswordRetrieval=""false"" enablePasswordReset=""true"" requiresQuestionAndAnswer=""false"" applicationName=""/"" requiresUniqueEmail=""false"" passwordFormat=""Hashed"" maxInvalidPasswordAttempts=""5"" minRequiredPasswordLength=""1"" minRequiredNonalphanumericCharacters=""0"" passwordAttemptWindow=""10"" passwordStrengthRegularExpression="""" type=""System.Web.Security.SqlMembershipProvider,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"" />", _defaultMembershipProvider, _connectionStringName))
                    );

            modifications.Add(
                new ModificationEntry(
                    string.Format("add[@name='{0}']", _defaultMembershipRoleProvider),
                    "configuration/system.web/roleManager/providers",
                    string.Format(@"<add name=""{0}"" connectionStringName=""{1}"" applicationName=""/"" type=""System.Web.Security.SqlRoleProvider,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"" />", _defaultMembershipRoleProvider, _connectionStringName))
                    );


            modifications.Add(
                new ModificationEntry(
                    "add[@name='readerQuotas']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<readerQuotas maxDepth=""32"" maxStringContentLength=""8192"" maxArrayLength=""16384"" maxBytesPerRead=""4096"" maxNameTableCharCount=""16384"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='reliableSession']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<reliableSession ordered=""true"" inactivityTimeout=""00:10:00"" enabled=""false"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='security']",
                    "configuration/system.serviceModel/bindings/wsHttpBinding/binding",
                    @"<security mode=""None"" />")
                    );

            modifications.Add(
                new ModificationEntry(
                    "add[@name='identity']",
                    "configuration/system.serviceModel/client/endpoint/identity",
                    string.Format(@"<servicePrincipalName value=""{0}"" />", ServicePrincipalName))
                    );



            return modifications.ToArray();
        }

        /// <summary>
        /// Holds the ModificationEntry objects that must be applied as attributes.
        /// </summary>
        protected override ModificationEntry[] GetAttributeEntries()
        {

            List<ModificationEntry> modifications = new List<ModificationEntry>();
            modifications.Add(new ModificationEntry("defaultProvider", "configuration/system.web/membership", _defaultMembershipProvider));
            modifications.Add(new ModificationEntry("enabled", "configuration/system.web/roleManager", "true"));
            modifications.Add(new ModificationEntry("defaultProvider", "configuration/system.web/roleManager", _defaultMembershipRoleProvider));
            modifications.Add(new ModificationEntry("mode", "configuration/system.web/authentication", "Forms"));
            modifications.Add(new ModificationEntry("loginUrl", "configuration/system.web/authentication/forms", "/Pages/sign_up.aspx"));
            modifications.Add(new ModificationEntry("address", "configuration/system.serviceModel/client/endpoint", DefaultEndPointAddress));

            //TODO: Test it
            modifications.Add(new ModificationEntry("name", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "WSHttpBinding_IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("closeTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("openTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("receiveTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:10:00"));
            modifications.Add(new ModificationEntry("sendTimeout", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "00:01:00"));
            modifications.Add(new ModificationEntry("bypassProxyOnLocal", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));
            modifications.Add(new ModificationEntry("transactionFlow", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));
            modifications.Add(new ModificationEntry("hostNameComparisonMode", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "StrongWildcard"));
            modifications.Add(new ModificationEntry("maxBufferPoolSize", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "524288"));
            modifications.Add(new ModificationEntry("maxReceivedMessageSize", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "2147483647"));
            modifications.Add(new ModificationEntry("messageEncoding", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "Text"));
            modifications.Add(new ModificationEntry("textEncoding", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "utf-8"));
            modifications.Add(new ModificationEntry("useDefaultWebProxy", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "true"));
            modifications.Add(new ModificationEntry("allowCookies", "configuration/system.serviceModel/bindings/wsHttpBinding/binding", "false"));

            modifications.Add(new ModificationEntry("binding", "configuration/system.serviceModel/client/endpoint", "wsHttpBinding"));
            modifications.Add(new ModificationEntry("bindingConfiguration", "configuration/system.serviceModel/client/endpoint", "WSHttpBinding_IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("contract", "configuration/system.serviceModel/client/endpoint", "CSP.MembershipInterface.IMembershipServiceContract"));
            modifications.Add(new ModificationEntry("name", "configuration/system.serviceModel/client/endpoint", "WSHttpBinding_IMembershipServiceContract"));
            return modifications.ToArray();
        }

    }
}
